package com.anji.hyperneat.onlinereinforcement;

import com.anji.hyperneat.nd.NDFloatArray;
import com.anji.hyperneat.nd.Util;
import com.anji.hyperneat.nd.NDFloatArray.MatrixIterator;

public class ActivatorNdAltTd extends ActivatorNDTemporalDifference {

	NDFloatArray[] runningGradientSums;
	

	public ActivatorNdAltTd(GridNetTD phenotype) {
		super(phenotype);
		
		runningGradientSums = new NDFloatArray[working.getWeights().length];

	}

	@Override
	public void updateNet(NDFloatArray rewards) {
		
		// w = w + alpha * (out_t+1 - out_t) * sum(lambda^t-k * gradient_k)
		// 

		
		if (null != lastGradients) {
			
			NDFloatArray tdErrs = calcTDErrs( rewards );
			
			updateGradientSum();
			
			for (int layer = 0; layer < working.getNumLayers()-1; layer++) {
				
				for (MatrixIterator w = working.getWeights()[layer].iterator()
						; w.hasNext()
						; w.next() ) {
					int[] wCoords = w.getCurrentCoordinates();
					float alpha = workingTd.getAlpha(layer, wCoords);
					
					float newVal = 0;
					
					
					
					for (MatrixIterator out = working.getOutputs().iterator(); out.hasNext(); out.next()) {
						int outIdx = out.getRawCoordinate();
						int[] outCoords = out.getCurrentCoordinates();	
						float lastOut = lastOutputs.getFromRawCoordinate(outIdx);
						
						newVal += alpha * (lastOut - out.get()) * sumGradients(layer, wCoords, outCoords);
					}					
					

					w.set(w.get() + newVal);
				}
			}
			
			
			
		}
		
		workingTd.decayLearningRates();
	}

	protected void updateGradientSum() {
		for (int layer = 0; layer < runningGradientSums.length; layer++) {
		for (MatrixIterator gradientSum = runningGradientSums[layer].iterator(); gradientSum.hasNext(); gradientSum.next()) {
			int[] coords = gradientSum.getCurrentCoordinates();
			float val = gradientSum.get();
//			val += workingTd.getL
			
		}
		
		}
		
	}

	protected float sumGradients(int layer, int[] wCoords, int[] outCoords) {
		lastGradients[layer].get(wCoords, outCoords);	runningGradientSums[layer].get(wCoords, outCoords);
		
//		float val = runningSum.get(wCoords, outCoords);
		return 0;
	}
	

	

}
